/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.panomedic.colors;

/**
 *
 * @author Yare
 */
abstract public class Pixel {

    /**  Array for pixel data */
    protected double[] comp = null;

    /**  Alpha channel   */
    protected boolean opaque = true;

    /**  Color space name */
    protected String name;
    
    public Pixel() {
        comp = new double[3];
        for (int i = 0; i < comp.length; i++) {
            comp[i] = 0;
        }
        opaque = false;
    }


    abstract public String getName();
    abstract public int[] getRGBA();

     /**
     * Powers each component by corresponding value of given array
     */ 
    public void powArray( double[] value ){
        for (int i = 0; i < 3; i++){
            comp[i] = Math.pow(comp[i],value[i]);
        }
    }
    /**
     * Multiplies each component by corresponding value of given array
     */ 
    public void mulArray( double[] value ){
        for (int i = 0; i < 3; i++){
            comp[i] *= value[i];
        }
    }
    /**
     * Adds each value of given array to values of components
     */ 
    public void addArray( double[] value ){
        for (int i = 0; i < 3; i++){
            comp[i] += value[i];
        }
    }
    public void contract( int[] maxValues, double[] minShift, double[] divider){
        for (int i = 0; i < minShift.length; i++) {
            comp[i] = (comp[i] + minShift[i]) * maxValues[i] / divider[i];
        }
    }

    /** gets the pixel data - 3 component array */
    public double[] getComp(){
        return comp;
    }

    /** from 2 pixels computes their avg (and adds 2 shifts) - component dealt 1 by 1
     * and saves it to Pixel.comp
     * Formula: (pixel1 + pixel2 + shift1 + shift2) / 2
     */
    public void mean2Comp(Pixel comp1, Pixel comp2, double[] shift1, double[] shift2){
        for (int i = 0; i < comp.length; i++) {
            comp[i] = (comp1.getComp()[i] + comp2.getComp()[i] + shift1[i] + shift2[i]) / 2;
        }
    }
    /** from 2 pixels computes their avg - component dealt 1 by 1
     * and saves it to Pixel.comp
     * Formula: (pixel1 + pixel2) / 2
     */
    public void mean2Comp(Pixel comp1, Pixel comp2) {
         for (int i = 0; i < comp.length; i++) {
            comp[i] = (comp1.getComp()[i] + comp2.getComp()[i]) / 2;
        }
    }
    
    /**
     * Set component (not opaque) values from the given RGB(A) array
     * @param rgba
     */
    abstract  public void setComp(int[] rgba);
    
    public void setComp(double[] comp){
        this.comp[0] = comp[0];
        this.comp[1] = comp[1];
        this.comp[2] = comp[2];
    }

    public void setOpaque(boolean opaque) {
        this.opaque = opaque;
    }
    
    public boolean isOpaque() {
        return opaque;
    }
    
    @Override
    public String toString() {
        String s = new String();
        for (int i = 0; i < comp.length; i++) {
           comp[i] = Math.floor(comp[i]*1000) / 1000;
        }
        s += getName() +": [" + comp[0] + ", " + comp[1] + ", " + comp[2] +"]";
        return s;
    }
    
    public static Pixel getPixel(int type){
        return getPixel(type, null);
    }
    
    public static Pixel getPixel(int type, int[] rgba){
        if (type < 0 || type >= ColorConstants.NUM_CS)
            return null;
        
        switch(type) {
            case(ColorConstants.RGB):  return new RGBPixel(rgba);
            case(ColorConstants.HSV):  return new HSVPixel(rgba);
            case(ColorConstants.Yxy):  return new YxyPixel(rgba);
            case(ColorConstants.Lab):  return new LabPixel(rgba);
            case(ColorConstants.LCh):  return new LChPixel(rgba);
            case(ColorConstants.Luv):  return null; //return new LuvPixel(rgba);
            default:                   return null;
        }
    }

}
